package org.oschina.queue.batchupdate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PreDestroy;
import org.oschina.Constants;
import org.oschina.helper.query.bak.IQueryHelper_bak;
import org.oschina.queue.BaseQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 批量更新队列
 */
@Component
public class BatchUpdateQueue extends BaseQueue {

	private final static Logger logger=LoggerFactory.getLogger(BatchUpdateQueue.class);
	
	@Autowired
	private IQueryHelper_bak queryHelper;
	
	private final int UPDATE_TIME=10; //强制更新时间
	private final int CACHE_COUNT=10; //最大缓存数量
	
	@Scheduled(fixedDelay=1000)
	private synchronized void handle()
	{
		BatchUpdateBean bean=(BatchUpdateBean)get(Constants.QUEUE_BATCH_UPDATE, BatchUpdateBean.class);
		push(bean);
		
		if(isUpdate())
			update();
	}
	
	private void push(BatchUpdateBean batchUpdateBean)
	{
		if(batchUpdateBean==null)
			return;
		
		getCacheHelper().lpush(getKey(), batchUpdateBean, getTimeout());
	}
	
	private boolean isUpdate()
	{
		int count=(int) getCacheHelper().llen(getKey());
		return (count!=0 && (isUpdate(UPDATE_TIME) || count==CACHE_COUNT));
	}

	private void update()
	{
		List<BatchUpdateBean> beans=getCacheHelper().lget(getKey(), 0, -1, BatchUpdateBean.class);
		getCacheHelper().del(getKey());
		
		Map<String,List<Object[]>> groupBySql=new HashMap<String,List<Object[]>>();
		for(BatchUpdateBean bean:beans)
		{
			List<Object[]> args=groupBySql.get(bean.getSql());
			if(args==null)
			{
				args=new ArrayList<Object[]>();
				groupBySql.put(bean.getSql(), args);
			}
			args.add(bean.getArgs());
		}
		
		Set<String> sqls=groupBySql.keySet();
		for(String sql:sqls)
		{
			List<Object[]> args=groupBySql.get(sql);
			logger.info("{} 个 '{}' 执行完成",args.size(),sql);
			queryHelper.batchUpdate(sql,args);
		}
	}
	
	private String getKey()
	{
		return Constants.CACHE_BATCH_UPDATE;
	}
	
	private int getTimeout()
	{
		return Constants.TIMEOUT_BATCH_UPDATE;
	}
	
	@PreDestroy
	private void preDestroy()
	{
		update();
	}
}